
#include <stdlib.h>


#include <stdio.h>

/*
 * morestring.c
 *
 *  Created on: Sep 8, 2008
 *      Author: lindenb
 */
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <stdarg.h>
#include <ctype.h>
#include <limits.h>
#include "lang/morestring.h"
#include "lang/morestdlib.h"

static const int DEFAULT_FORMAT_SIZE=50;

 malloc_string strfmt(const char* fmt,...)
	{
	/* Guess we need no more than 100 bytes. */
	   int size = DEFAULT_FORMAT_SIZE;
	   char *p;

	   if ((p = Malloc(size)) == NULL) return NULL;

	   while (true)
		   {
		   char *np;
		   va_list ap;
		   int n=0;
		   /* Try to print in the allocated space. */
		   va_start(ap, fmt);
		   n = vsnprintf(p, size, fmt, ap);
		   va_end(ap);
		   /* If that worked break the loop. */
		   if (n > -1 && n < size)
			   {
			   break;
			   }

		   size*=2;
		   if ((np = Realloc (p, size)) == NULL)
			   {
			   Free(p);
			   return NULL;
			   }
		   else
			   {
			   p = np;
			   }
		   }
	   return p;
		}

int strIsEmpty(const char* s)
	{
	return s==NULL || s[0]==0;
	}

int strLastIndexOfChar(const char* s,int c)
	{
	char *p= rindex(s,c);
	return p==NULL?-1:p-s;
	}


int strLastIndexOfString(const char* s,const char* searched)
	{
        char* p1=(char*)s;
        char* max=NULL;
        while(1)
            {
            p1=strstr(p1,searched);
            if(p1==NULL) break;
            max=p1;
            p1++;
            }
        if(max==NULL) return -1;
        return (int)(max-s);
	}


malloc_string substr(const char* s,int start,int end)
	{
	int len=(end-start);
	char* p=Malloc(len+1);
	if(p==NULL) return NULL;
	memcpy(p,&s[start],len);
	p[len]=0;
	return p;
	}

malloc_string readline(FILE* in)
      {
     int found=0;
      int c;
      int size=0;
      int bufsize = BUFSIZ;
      char *p;
      assert(in!=NULL);
       if ((p = Malloc(bufsize)) == NULL) return NULL;

       while ((c=fgetc(in))!=EOF)
               {
               found=1;
                if(c=='\n') break;

                if(size+2< bufsize)
                    {
                    char* np;
                    bufsize*=2;
                    np =  Realloc (p, bufsize);
                    if(np==NULL)
                        {
                        Free(p);
                        return NULL;
                        }
                    p=np;
                    }
                p[size]=c;
                ++size;
               }
          if(found==0)
            {
            Free(p);
            return NULL;
            }

         p[size]=0;
         if(size>0 && p[size-1]=='\r')
            {
            p[size-1]=0;
            }
         return p;
         }

int strIsInteger(const char* s)
    {
    char *p2=NULL;
    int n = strtol(s,&p2,10);
    if(n== LONG_MIN || n== LONG_MAX ) return 0;
    while(*p2!=0)
        {
        if(!isspace(*p2)) return 0;
        ++p2;
        }
    return 1;
    }

char* ltrim(char *str)
    {
     char* p=str;
     int len;
     if(str==NULL) return NULL;
     len=strlen(str);
     while(*p!=0 && isspace(*p))
        {
        ++p;
        }
     memmove(str,p,sizeof(char)*(len-(p-str)));
     return str;
     }

char* rtrim(char *str)
    {
    char* p;
    int len;
    if(str==NULL) return NULL;
    len=strlen(str);
    if(len==0) return str;
    p=&str[len-1];
    while(p!=str)
        {
        if(!isspace(*p)) break;
        *p=0;
        --p;
        }
    return str;
    }

char* trim(char *s)
    {
    return rtrim(ltrim(s));
    }

StringArrayPtr strSplit(const char* line,int c)
    {
    char* prev=(char*)line;
    char* curr=(char*)line;
    StringArrayPtr array= stringArray_new();
    if(array==NULL) return NULL;
    assert(line!=NULL);

    while(1)
        {
        if(*curr==c || *curr==0)
            {
            int len=curr-prev;
            char* p= (char*)Malloc(len+1);
            if(p==NULL)
                {
                stringArray_delete(array);
                return NULL;
                }
            memcpy(p,prev,len);
            p[len]=0;

            if(stringArray_addElement(array,p)!=0)
                {
                Free(p);
                stringArray_delete(array);
                return NULL;
                }
            Free(p);
            prev=curr+1;
            if(*curr==0) break;
            }
        ++curr;
        }
    return array;
    }

StringArrayPtr stringArray_new()
    {
    StringArrayPtr ptr= (StringArrayPtr)Malloc(sizeof(StringArray));
    if(ptr==NULL) return NULL;
    ptr->_size=0;
    ptr->_data= (malloc_string*)Calloc(1,sizeof(malloc_string));
    if(ptr->_data==NULL)
        {
        Free(ptr);
        return NULL;
        }
    return ptr;
    }

int stringArray_size(StringArrayPtr ptr)
    {
    assert(ptr!=NULL);
    return ptr->_size;
    }

const char* stringArray_at(StringArrayPtr ptr,int index)
    {
    assert(ptr!=NULL);
    assert(index>=0);
    assert(index< stringArray_size(ptr));
    return ptr->_data[index];
    }
int stringArray_addElement(StringArrayPtr ptr,const char* newstring)
    {
    malloc_string* ss;
    char* p;
    assert(ptr!=NULL);
    assert(newstring!=NULL);

    ss= (malloc_string*)Realloc(
            ptr->_data,
            (stringArray_size(ptr)+2)*sizeof(malloc_string)
            );
    if(ss==NULL) return -1;
    ptr->_data=ss;

    p= strdup(newstring);
    if(newstring==NULL)
        {
        return -1;
        }
    ptr->_data[ ptr->_size]= p;
    memset( &ptr->_data[ ptr->_size+1],sizeof(malloc_string),0);
    ptr->_size++;
    return 0;
    }

void stringArray_delete(StringArrayPtr ptr)
    {
    int i=0;
    if(ptr==NULL) return;
    for(i=0;i< ptr->_size;++i)
        {
        Free(ptr->_data[i]);
        }
    Free(ptr->_data);
    Free(ptr);
    }

malloc_string strAppendString(malloc_string str,const char* what)
	{
	malloc_string ptr;
	int len1= (str==NULL?0:strlen(str));
	int len2= 0;
	assert(what!=NULL);
	len2=strlen(what);
	ptr= (char*)Realloc(str,sizeof(char)*(len1+len2+1));
	if(ptr==NULL) return NULL;
	memcpy(&ptr[len1],what,(len2+1)*sizeof(char));
	return ptr;
	}

 malloc_string strAppendChar(malloc_string str,char c)
	 {
	 char what[2]={c,0};
	 return strAppendString(str,what);
	 }

 int strPrintEscape(const char* s, FILE* out)
	 {
	 char* p=(char*)s;
	 while(*p!=0)
		 {
		 switch(*p)
			 {
			 case '\"': fputs("\\\"",out); break;
			 case '\'': fputs("\\\'",out); break;
			 case '\n': fputs("\\n",out); break;
			 case '\r': fputs("\\r",out); break;
			 case '\t': fputs("\\t",out); break;
			 case '\b': fputs("\\b",out); break;
			 case '\v': fputs("\\v",out); break;
			 default: fputc(*p,out);break;
			 }
		 ++p;
		 }
	return 0;
	 }

 int strStartsWith(const char* s, const char* substr)
	 {
	 return strncmp(s,substr,strlen(substr))==0?1:0;
	 }
